#include "my_iic.h"
#define IIC_ADDR	0xC2

mI2C_t miic={0};

void iic_callback(u8 type);
void uart8_send(u8* buf, u16 len);
//硬件接口
//SDA PD4
//SCL PD5

static void i2c_IoInit(void){
	//io初始化输入
	GPIO_InitTypeDef GPIO_Initure;

	GPIO_Initure.Pin = GPIO_PIN_4| GPIO_PIN_5;
	GPIO_Initure.OutputEn = DISABLE;
	GPIO_Initure.InputEn = ENABLE;
	GPIO_Initure.PullupEn = DISABLE;
	HAL_GPIO_Init(GPIOD, &GPIO_Initure);
}

static void i2c_SdaH(void){
	HAL_GPIO_SetInOut(GPIOD, GPIO_PIN_4, ENABLE, DISABLE);
	HAL_GPIO_WritePin(GPIOD, GPIO_PIN_4, GPIO_PIN_RESET);
}

static void i2c_SdaL(void){
	HAL_GPIO_SetInOut(GPIOD, GPIO_PIN_4, ENABLE, ENABLE);
	HAL_GPIO_WritePin(GPIOD, GPIO_PIN_4, GPIO_PIN_RESET);
}

static void i2c_SclH(void){
	HAL_GPIO_SetInOut(GPIOD, GPIO_PIN_5, ENABLE, DISABLE);
	HAL_GPIO_WritePin(GPIOD, GPIO_PIN_5, GPIO_PIN_RESET);
}

static void i2c_SclL(void){
	HAL_GPIO_SetInOut(GPIOD, GPIO_PIN_5, ENABLE, ENABLE);
	HAL_GPIO_WritePin(GPIOD, GPIO_PIN_5, GPIO_PIN_RESET);
}

static u8 i2c_ReadSda(void){
	return HAL_GPIO_ReadPin(GPIOD, GPIO_PIN_4);
}

static u8 i2c_ReadScl(void){
	return HAL_GPIO_ReadPin(GPIOD, GPIO_PIN_5);
}

/*   sta
0 空闲 超时或者收到stop置0
1 收到起始信号 		准备接收设备id
2 设备id接收完成		准备ack或者nack
3 ack完成			准备进入收发状态或者挂起
4 挂起				等待stop
5 进入接收状态		准备接收数据
6 执行ack
7 进入发送状态		准备发送数据
8 等待主机ack
*/
void sda_h(void)
{
	if(i2c_ReadScl()==1){		//停止信号
		miic.sta=0;
		iic_callback(0);
	}
	
}

void sda_l(void)
{
	if(i2c_ReadScl()==1){		//起始信号
		miic.sta=1;
		miic.bit_id=0;
	}
}

void scl_h(void)
{
	//scl变高，此时应该读取电平
	if(miic.sta==1){
		miic.dev_addr<<=1;
		miic.dev_addr|=i2c_ReadSda();
		miic.bit_id++;
		if(miic.bit_id>=8){
			miic.sta=2;
			miic.value=miic.dev_addr;
			iic_callback(2);
		}
	}
	else if(miic.sta==5){
		miic.value<<=1;
		miic.value|=i2c_ReadSda();
		miic.bit_id++;
		if(miic.bit_id>=8){
			miic.sta=6;
			
			iic_callback(2);	//从缓冲读数据，此处接收中断
		}
	}
	else if(miic.sta==8){
		if(i2c_ReadSda()==0){
			miic.sta=3;
		}
		else{	//NACK
			miic.sta=4;
			iic_callback(4);
		}
	}
}

void scl_l(void)		//scl变低，此时应该改变电平
{
	if(miic.sta==2){
		miic.sta=3;
		if((miic.dev_addr&0xFE)==IIC_ADDR){	//设备地址校验通过
			i2c_SdaL();	//ACK
			miic.bit_id=0;
			
		}
		else{	//非本设备操作
			i2c_SdaH();	//NACK
			miic.sta=4;
		}
	}
	else if(miic.sta==3){
		
		if((miic.dev_addr&0x01)==1){	//主机读
			miic.sta=7;
			miic.bit_id=0;
			iic_callback(3);	//填数据到缓冲 此处发送中断
			if(miic.value & 0x80){
				i2c_SdaH();
			}
			else{
				i2c_SdaL();
			}
			miic.value<<=1;
			miic.bit_id++;
		}
		else{							//主机写
			i2c_SdaH();	//释放总线
			miic.sta=5;
			miic.bit_id=0;
		}
	}
	else if(miic.sta==6){
		i2c_SdaL();	//ACK
		miic.sta=3;
	}
	else if(miic.sta==7){
		if(miic.bit_id<8){
			if(miic.value & 0x80){
				i2c_SdaH();
			}
			else{
				i2c_SdaL();
			}
			miic.value<<=1;
			miic.bit_id++;
		}
		else{
			i2c_SdaH();
			miic.sta=8;
			
			
		}
	}
}

void iic_callback(u8 type)
{
	u8 write_addr=0;
	u8 send_addr=0;
	u8 tmp_data;	
	switch(type)
	{
		case 0:{ //空闲         
			miic.tx_index = 0;
			miic.rx_index = 0;
		}break;
//		case 1:{ //        
//			miic.tx_index = 0;
//			miic.rx_index = 0;
//		}break;
		case 2:{ //接收中断           
			miic.rx_buf[ miic.rx_index ] = miic.value;
			miic.rx_index++;
			if(miic.rx_index>=20) miic.rx_index=20-1;	//防溢出
			
			if(miic.rx_index == 2){		//接收到寄存器地址
				miic.addr = miic.rx_buf[1];     
				miic.tx_index = 0;
			}
			else if(miic.rx_index > 2){	//接收写入数据
				write_addr=miic.addr+miic.rx_index-3;
				miic.reg[write_addr]=miic.rx_buf[ miic.rx_index -1 ];		//写入到参数表  无验证
				
			}
		}break;
		case 3:{ //发送中断		
			send_addr=miic.addr + miic.tx_index;
			tmp_data = miic.reg[send_addr];
			miic.tx_index=miic.tx_index+1;
			miic.value =tmp_data;
		}break;
		case 4:{ //主机回UACK
			miic.tx_index = 0;
		}break;
		default:
			
		break;
    }
}



void my_iic_init(void)
{
	i2c_IoInit();

}

//扫描io
void my_iic_task(void)
{
	static u8 sda=0;
	static u8 scl=0;
	static u8 sda_old=0;
	static u8 scl_old=0;

	sda=HAL_GPIO_ReadPin(GPIOD,GPIO_PIN_4);
	scl=HAL_GPIO_ReadPin(GPIOD,GPIO_PIN_5);

	if(sda_old!=sda){
		if(sda==0){
			sda_l();
		}
		else{
			sda_h();
		}
		sda_old=sda;
	}
	if(scl_old!=scl){
		if(scl==0){
			scl_l();
		}
		else{
			scl_h();
		}
		scl_old=scl;
	}
}


